﻿using SqlSugar;
using System.IO;

namespace Net8.Project.Common.DB
{
    /// <summary>
    /// 数据库基础配置类，支持多库、主从、故障转移等功能。
    /// </summary>
    public class BaseDBConfig
    {
        /// <summary>
        /// 所有数据库连接配置
        /// </summary>
        public static readonly List<ConnectionConfig> AllConfigs = new();

        /// <summary>
        /// 有效的数据库连接配置（排除日志库）
        /// </summary>
        public static List<ConnectionConfig> ValidConfig = new();

        /// <summary>
        /// 主库连接配置
        /// </summary>
        public static ConnectionConfig MainConfig;

        /// <summary>
        /// 日志库连接配置
        /// </summary>
        public static ConnectionConfig LogConfig;

        /// <summary>
        /// 是否为多库模式
        /// </summary>
        public static bool IsMulti => ValidConfig.Count > 1;

        /*
         * 目前为多库操作，默认加载appsettings.json中设置为true的第一个db连接。
         * 新增主库备用连接，主库无法连接时自动切换到备用连接。
         * 主库ConfigId+任意数字作为备用ConfigId，只要不重复即可。
         */

        /// <summary>
        /// 获取所有数据库和从库的配置信息
        /// </summary>
        public static (List<MutiDBOperate> allDbs, List<MutiDBOperate> slaveDbs) MutiConnectionString => MutiInitConn();

        /// <summary>
        /// 初始化多数据库连接配置，主库排在第一个
        /// </summary>
        /// <returns>主库和从库的配置信息</returns>
        public static (List<MutiDBOperate>, List<MutiDBOperate>) MutiInitConn()
        {
            // 从配置文件读取所有启用的数据库
            var listdatabase = AppSettings.App<MutiDBOperate>("DBS")
                .Where(i => i.Enabled).ToList();
            var mainDbId = AppSettings.App("MainDB").ToString();
            var mainDbModel = listdatabase.Single(d => d.ConnId == mainDbId);
            listdatabase.Remove(mainDbModel);
            listdatabase.Insert(0, mainDbModel);

            // 定制每个数据库的连接字符串
            foreach (var db in listdatabase) SpecialDbString(db);
            return (listdatabase, mainDbModel.Slaves);
        }

        /// <summary>
        /// 安全获取数据库连接字符串，优先从本地txt文件读取，若不存在则用配置中的字符串
        /// </summary>
        /// <param name="conn">连接字符串或本地文件路径</param>
        /// <returns>最终连接字符串</returns>
        private static string DifDBConnOfSecurity(params string[] conn)
        {
            foreach (var item in conn)
            {
                try
                {
                    if (File.Exists(item))
                    {
                        return File.ReadAllText(item).Trim();
                    }
                }
                catch
                {
                    // 忽略异常，继续尝试下一个
                }
            }
            // 如果都不是文件，则返回最后一个参数
            return conn[^1];
        }

        /// <summary>
        /// 定制数据库连接字符串（如sqlite拼接路径，其他类型优先读取本地安全文件）
        /// </summary>
        /// <param name="mutiDBOperate">数据库操作对象</param>
        /// <returns>定制后的数据库操作对象</returns>
        private static MutiDBOperate SpecialDbString(MutiDBOperate mutiDBOperate)
        {
            switch (mutiDBOperate.DbType)
            {
                case DataBaseType.Sqlite:
                    mutiDBOperate.Connection =
                        $"DataSource={Path.Combine(Environment.CurrentDirectory, mutiDBOperate.Connection)}";
                    break;
                case DataBaseType.SqlServer:
                    mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_SqlserverConn.txt",
                        mutiDBOperate.Connection);
                    break;
                case DataBaseType.MySql:
                    mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_MySqlConn.txt",
                        mutiDBOperate.Connection);
                    break;
                case DataBaseType.Oracle:
                    mutiDBOperate.Connection = DifDBConnOfSecurity(@"D:\my-file\dbCountPsw1_OracleConn.txt",
                        mutiDBOperate.Connection);
                    break;
                // 其他类型可按需扩展
            }
            return mutiDBOperate;
        }
    }

    /// <summary>
    /// 数据库类型枚举
    /// </summary>
    public enum DataBaseType
    {
        MySql = 0,
        SqlServer = 1,
        Sqlite = 2,
        Oracle = 3,
        PostgreSQL = 4,
        Dm = 5,
        Kdbndp = 6,
    }

    /// <summary>
    /// 多数据库操作配置
    /// </summary>
    public class MutiDBOperate
    {
        /// <summary>
        /// 连接启用开关
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// 连接ID
        /// </summary>
        public string ConnId { get; set; }

        /// <summary>
        /// 从库执行优先级，值越大越优先
        /// </summary>
        public int HitRate { get; set; }

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string Connection { get; set; }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public DataBaseType DbType { get; set; }

        /// <summary>
        /// 从库列表
        /// </summary>
        public List<MutiDBOperate> Slaves { get; set; }
    }
}
